package com.yzy.fly.service.util;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.yzy.fly.util.FieldUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Slf4j
public class MethodInvokeUtil {
    public static final Map<String,String> value = Maps.newHashMap();

    public static <T> T invokeWithAnnotationPresent(Object instance,Class clz,Class annotation){
        Object result = null;
        Method[] declaredMethods = clz.getDeclaredMethods();
        for (int i = 0; i < declaredMethods.length; i++) {
            Method declaredMethod = declaredMethods[i];
            if (declaredMethod.isAnnotationPresent(annotation)) {
                result = invoke(instance,declaredMethod);
            }
        }
        return (T)result;
    }

    public static <T> T invoke(Object instance,Method method){
        Object result = null;
        try {
            result = method.invoke(instance);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return (T)result;
    }

    public static List<Method> findMethodAnnotationPresent(Class clz, Class annotation){
        List<Method> methods = Lists.newArrayListWithCapacity(0);
        Method[] declaredMethods = clz.getDeclaredMethods();
        if (ArrayUtils.isNotEmpty(declaredMethods)) {
            for (int i = 0; i < declaredMethods.length; i++) {
                Method declaredMethod = declaredMethods[i];
                if (declaredMethod.isAnnotationPresent(annotation)) {
                    methods.add(declaredMethod);
                }
            }
        }
        return methods;
    }

    public static Method findGetterMethodByField(Class clz, Field field){
        String getterName = "get"+ FieldUtil.upperFirst(field.getName());
        Method getterMethod = findMethodByName(clz,getterName);
        return getterMethod;
    }

    public static Method findSetterMethodByField(Class clz, Field field){
        String setterName = "set"+ FieldUtil.upperFirst(field.getName());
        Method setterMethod = findMethodByName(clz,setterName,field.getType());
        return setterMethod;
    }
    public static Method findMethodByName(Class clz, String methodName,Class<?>... parameterTypes){
        Method getterMethod = null;
        try {
            getterMethod = clz.getDeclaredMethod(methodName,parameterTypes);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        return getterMethod;
    }

}
